package com.xugongzhang.aop.aspect;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

/**
 * @author X
 * @date 2022/12/6 22:12
 * 日志切面类，里面有通知方法
 */
@Slf4j
@Aspect
@Component
public class LogAspects {
    
    // 切点都是同一个方法，所以写一个方法定义切点
    @Pointcut("execution(public int com.xugongzhang.aop.utils.MathCalculator.*(..))")
    public void pointCut() {
    }
    
    // *** joinPoint一定要放在第一个参数 ***
    // 切点表达式（指定在哪个方法切入）
    // 前置通知，在目标方法运行之前运行
    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        log.info("除法 {} 开始，参数是 {}...", signature.getName(), JSON.toJSONString(joinPoint.getArgs()));
    }
    // 后置通知，在目标方法运行结束之后运行，无论方法正常结束还是异常结束都调用
    @After("com.xugongzhang.aop.aspect.LogAspects.pointCut()")
    public void logEnd() {
        log.info("除法结束...");
    }
    // 返回通知
    @AfterReturning(value = "pointCut()", returning = "result")
    public void logReturn(JoinPoint joinPoint, int result) {
        log.info("除法 {} 返回 {}...", joinPoint.getSignature().getName(), result);
    }
    // 异常通知
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void logError(JoinPoint joinPoint, Exception exception) {
        log.info("除法 {} 异常 {}...", joinPoint.getSignature().getName(), exception.getMessage());
    }
    // 环绕通知，动态代理，手动推进目标方法运行
}
